import json
import sys
from datetime import datetime
from os import path
from random import choice

from PyQt5.QtWidgets import (
    QApplication,
    QLabel,
    QWidget,
    QVBoxLayout,
    QSystemTrayIcon,
    QMenu,
    QAction,
    QGraphicsDropShadowEffect,
    QScrollArea,
)
from PyQt5.QtGui import QIcon, QColor
from PyQt5.QtCore import Qt, QTimer


class ConfigManager:
    DEFAULT_SETTINGS = {
        "position": [200, 100],
        "background_color_day": "rgba(255, 255, 255, 200)",
        "background_color_night": "rgba(25, 25, 25, 200)",
        "font_color_day": "rgba(0, 0, 0, 255)",
        "font_color_night": "rgba(255, 255, 255, 225)",
        "shadow_color_day": "rgba(125, 125, 125, 180)",
        "shadow_color_night": "rgba(25, 25, 25, 180)",
        "good_morning_time": "06:00",
        "good_night_time": "22:00",
        "keep_on_top": True,
        "update_interval": 3600,  # 每小时更新一次
        "max_explanation_length": 100,  # 释义最大长度
        "default_content_type": "explanation",  # 默认显示内容类型：explanation（释义）, derivation（出处）, example（例句）
    }

    def __init__(self, settings_file="settings.json"):
        self.settings_file = settings_file
        self.load_settings()

    def load_settings(self):
        try:
            with open(self.settings_file, "r") as file:
                self.settings = json.load(file)
        except (FileNotFoundError, json.JSONDecodeError):
            self.settings = self.DEFAULT_SETTINGS
            self.save_settings()

    def save_settings(self):
        with open(self.settings_file, "w") as file:
            json.dump(self.settings, file, indent=4)

    def get_setting(self, key):
        return self.settings.get(key, self.DEFAULT_SETTINGS[key])

    def set_setting(self, key, value):
        self.settings[key] = value
        self.save_settings()


class IdiomManager:
    def __init__(self, json_file="idiom.json"):
        self.json_file = json_file
        self.idioms = None
        self.load_idioms()

    def load_idioms(self):
        try:
            with open(self.json_file, "r", encoding="utf-8") as f:
                self.idioms = json.load(f)
        except FileNotFoundError:
            print(f"Error: {self.json_file} not found!")
            sys.exit(1)
        except json.JSONDecodeError:
            print(f"Error: {self.json_file} is not a valid JSON file!")
            sys.exit(1)

    def get_random_idiom(self):
        return choice(self.idioms) if self.idioms else None

    def get_idiom_by_word(self, word):
        return next((i for i in self.idioms if i["word"] == word), None)


class IdiomWidget(QWidget):
    def __init__(self, app: QApplication):
        super().__init__()

        self.app = app
        self.config_manager = ConfigManager()
        self.idiom_manager = IdiomManager()
        self.current_content_type = self.config_manager.get_setting("default_content_type")
        self.initUI()
        self.create_tray_icon()
        self.create_tray_menu()
        self.create_timer()
        self.update_idiom()
        self.drag_position = None

    def create_tray_icon(self):
        self.tray_icon = QSystemTrayIcon(self)
        self.tray_icon.setIcon(QIcon("icon.svg"))
        self.tray_icon.setVisible(True)

    def create_tray_menu(self):
        tray_menu = QMenu()
        
        # 添加置顶选项
        keep_top_action = QAction("置顶显示", self, checkable=True)
        keep_top_action.setChecked(self.config_manager.get_setting("keep_on_top"))
        keep_top_action.triggered.connect(self.toggle_keep_on_top)
        tray_menu.addAction(keep_top_action)
        
        # 添加居中显示选项
        center_action = QAction("居中显示", self)
        center_action.triggered.connect(self.move_to_center)
        tray_menu.addAction(center_action)
        
        # 添加分隔线
        tray_menu.addSeparator()
        
        # 添加退出选项
        exit_action = QAction("退出", self)
        exit_action.triggered.connect(self.close)
        tray_menu.addAction(exit_action)
        
        self.tray_icon.setContextMenu(tray_menu)

    def toggle_keep_on_top(self, checked):
        self.config_manager.set_setting("keep_on_top", checked)
        if checked:
            self.setWindowFlags(self.windowFlags() | Qt.WindowStaysOnTopHint)
        else:
            self.setWindowFlags(self.windowFlags() & ~Qt.WindowStaysOnTopHint)
        self.show()

    def move_to_center(self):
        screen = QApplication.primaryScreen()
        center = screen.availableGeometry().center()
        self.move(center - self.rect().center())
        self.config_manager.set_setting("position", [self.x(), self.y()])

    def close(self):
        super().close()
        self.app.exit()

    def create_timer(self):
        self.timer = QTimer(self)
        self.timer.timeout.connect(self.update_idiom)
        update_interval = (
            self.config_manager.get_setting("update_interval") * 1000
        )  # 转换为毫秒
        self.timer.start(update_interval)

    def is_night(self):
        now = datetime.now()
        day_start = self._create_time_from_setting("good_morning_time")
        night_start = self._create_time_from_setting("good_night_time")
        return now.time() < day_start.time() or now.time() >= night_start.time()

    def _create_time_from_setting(self, setting_key):
        time_str = self.config_manager.get_setting(setting_key)
        return datetime.fromisoformat(f"{datetime.now().date().isoformat()}T{time_str}")

    @property
    def background_color(self):
        return self.config_manager.get_setting(
            "background_color_night" if self.is_night() else "background_color_day"
        )

    @property
    def shadow_color(self):
        return self.parsingRgba(
            self.config_manager.get_setting(
                "shadow_color_night" if self.is_night() else "shadow_color_day"
            )
        )

    @property
    def font_color(self):
        return self.config_manager.get_setting(
            "font_color_night" if self.is_night() else "font_color_day"
        )

    def parsingRgba(self, rgba):
        rgb = rgba.replace("rgba", "").replace("(", "").replace(")", "").split(",")
        return QColor(int(rgb[0]), int(rgb[1]), int(rgb[2]), int(rgb[3]))

    def get_font_size(self, text):
        if len(text) <= 8:
            return "22px"
        if len(text) <= 12:
            return "20px"
        if len(text) <= 14:
            return "18px"
        return "16px"

    def update_style(self):
        # 根据成语长度调整字号
        idiom_text = self.idiom_label.text()
        font_size = self.get_font_size(idiom_text)

        self.idiom_label.setStyleSheet(
            f"""
            font-size: {font_size};
            font-weight: bold;
            font-family: "Microsoft YaHei", "SimHei", sans-serif;
            padding: 2px;
            background-color: {self.background_color};
            color: {self.font_color};
            border-radius: 8px;
        """
        )
        self.explanation_label.setStyleSheet(
            f"""
            font-size: 15px;
            font-family: "Microsoft YaHei", "SimHei", sans-serif;
            padding: 8px 12px;
            color: {self.font_color};
            background-color: {self.background_color};
            border-radius: 8px;
        """
        )

        # 更新滚动区域的样式
        self.findChild(QScrollArea).setStyleSheet(
            f"""
            QScrollArea {{
                border: none;
                background-color: {self.background_color};
                border-radius: 8px;
                padding: 0px;
            }}
        """
        )

        # 将阴影效果应用到成语标签
        shadow_effect = QGraphicsDropShadowEffect(self)
        shadow_effect.setBlurRadius(15)
        shadow_effect.setColor(self.shadow_color)
        shadow_effect.setOffset(3, 3)
        self.idiom_label.setGraphicsEffect(shadow_effect)

    def initUI(self):
        self.setWindowTitle("成语小组件")
        self.setWindowFlags(Qt.FramelessWindowHint | Qt.Tool)
        self.setAttribute(Qt.WA_TranslucentBackground)

        layout = QVBoxLayout()
        layout.setSpacing(4)
        
        # 成语标签
        self.idiom_label = QLabel(self)
        self.idiom_label.setAlignment(Qt.AlignCenter)
        self.idiom_label.setContextMenuPolicy(Qt.CustomContextMenu)
        self.idiom_label.customContextMenuRequested.connect(self.update_idiom)
        self.idiom_label.setFixedHeight(40)  # 固定成语标签高度
        self.idiom_label.setFixedWidth(300)  # 固定成语标签宽度
        
        # 释义标签和滚动区域
        scroll_area = QScrollArea()
        scroll_area.setWidgetResizable(True)
        scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)  # 禁用水平滚动条
        scroll_area.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)  # 禁用垂直滚动条
        scroll_area.setStyleSheet(f"""
            QScrollArea {{
                border: none;
                background-color: {self.background_color};
                border-radius: 8px;
            }}
        """)
        
        self.explanation_label = QLabel()
        self.explanation_label.setAlignment(Qt.AlignCenter)
        self.explanation_label.setWordWrap(True)
        self.explanation_label.setContextMenuPolicy(Qt.CustomContextMenu)
        self.explanation_label.customContextMenuRequested.connect(self.switch_content_type)
        self.explanation_label.setStyleSheet(f"""
            QLabel {{
                background-color: {self.background_color};
                border-radius: 8px;
            }}
        """)
        
        scroll_area.setWidget(self.explanation_label)
        scroll_area.setFixedHeight(90)  # 减小滚动区域高度
        
        layout.addWidget(self.idiom_label)
        layout.addWidget(scroll_area)
        self.setLayout(layout)

        position = self.config_manager.get_setting("position")
        self.setGeometry(position[0], position[1], 320, 150)  # 减小总高度

    def switch_content_type(self, position):
        content_types = ["explanation", "derivation", "example"]
        current_index = content_types.index(self.current_content_type)
        next_index = (current_index + 1) % len(content_types)
        self.set_content_type(content_types[next_index])

    def set_content_type(self, content_type):
        self.current_content_type = content_type
        self.config_manager.set_setting("default_content_type", content_type)
        self.update_idiom(change_idiom=False)  # 不改变成语

    def update_idiom(self, change_idiom=True):
        if change_idiom:
            idiom = self.idiom_manager.get_random_idiom()
            if idiom:
                self.idiom_label.setText(idiom["word"])
        else:
            idiom = self.idiom_manager.get_idiom_by_word(self.idiom_label.text())
            if not idiom:
                return

        content = idiom[self.current_content_type]
        if self.current_content_type == "example":
            content = content.replace("★", "\n★")  # 将例句中的★替换为换行符
        
        # 添加内容类型标识
        content_type_indicator = {
            "explanation": "【释义】：",
            "derivation": "【出处】：",
            "example": "【例句】："
        }
        content = content_type_indicator[self.current_content_type] + content
        
        self.explanation_label.setText(content)  # 直接显示完整内容
        self.update_style()

    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.drag_position = event.globalPos() - self.frameGeometry().topLeft()
            event.accept()

    def mouseMoveEvent(self, event):
        if event.buttons() == Qt.LeftButton and self.drag_position is not None:
            self.move(event.globalPos() - self.drag_position)
            event.accept()

    def mouseReleaseEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.drag_position = None
            QTimer.singleShot(1000, self.save_new_position)
            event.accept()

    def save_new_position(self):
        new_position = [self.x(), self.y()]
        self.config_manager.set_setting("position", new_position)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    idiom_widget = IdiomWidget(app)
    idiom_widget.show()
    sys.exit(app.exec_())
